package com.tanhua.server.service;

import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.Comment;
import com.tanhua.domain.mongo.FollowUser;
import com.tanhua.domain.mongo.Video;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.VideoVo;
import com.tanhua.dubbo.api.CommentApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VideoApi;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;

@Service
public class VideoService {

    @Reference
    private VideoApi videoApi;

    @Reference
    private UserInfoApi userInfoApi;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private FastFileStorageClient fastFileStorageClient;

    @Autowired
    private FdfsWebServer fdfsWebServer;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private VideoMQService videoMQService;

    @Reference
    private CommentApi commentApi;

    /**
     * 小视频列表
     */
    public PageResult queryVideoList(Integer page, Integer pagesize) {

        // 1.先查询redis中的推荐数据
        PageResult pageResult = findByRecommend(page, pagesize);

        if(pageResult == null){
            // 1.1 调用服务提供者api分页查询小视频列表
            pageResult = videoApi.queryVideoList(page, pagesize);
        }

        // 获取当前页的数据
        List<Video> videoList = (List<Video>) pageResult.getItems();

        // 2.封装返回数据
        List<VideoVo> voList = new ArrayList<>();

        if (videoList != null && videoList.size() > 0) {
            for (Video video : videoList) {
                // 2.1 创建vo
                VideoVo vo = new VideoVo();

                // 2.2 封装vo
                vo.setId(video.getId().toString());
                vo.setUserId(video.getUserId());
                vo.setCover(video.getPicUrl());
                vo.setVideoUrl(video.getVideoUrl());
                vo.setSignature(video.getText());
                vo.setLikeCount(video.getLikeCount());
                vo.setCommentCount(video.getCommentCount());

                // 根据小视频作者用户id查询详情
                UserInfo userInfo = userInfoApi.findById(video.getUserId());
                vo.setAvatar(userInfo.getAvatar());
                vo.setNickname(userInfo.getNickname());

                vo.setHasLiked(0);

                // 判断是否关注作者
                String key = "followUser_" + UserHolder.getUserId() + "_" + video.getUserId();
                if (redisTemplate.hasKey(key)) {
                    vo.setHasFocus(1);  // 已关注
                } else {
                    vo.setHasFocus(0);  // 未关注
                }

                // 2.3 添加vo到集合
                voList.add(vo);
            }
        }

        // 3.重新设置items的值
        pageResult.setItems(voList);

        return pageResult;
    }

    /**
     * 查询redis的推荐数据
     * @param page
     * @param pagesize
     * @return
     */
    private PageResult findByRecommend(Integer page, Integer pagesize) {
        // 1.拼接key
        String key = "QUANZI_VIDEO_RECOMMEND_" + UserHolder.getUserId();

        // 2.根据key从redis查询推荐动态的pid集合，10,8,31,38,22,7,26,11,10,10
        String value = redisTemplate.opsForValue().get(key);
        if (StringUtils.isEmpty(value)) {
            return null;
        }

        // 3.将value拆分成数组
        String[] vids = value.split(",");

        // 4.将数组转为list集合
        List<Long> vidList = new ArrayList<>();
        for (String vid : vids) {
            vidList.add(Long.valueOf(vid));
        }

        // 5.调用服务提供者api，根据pid集合分页查询
        PageResult pageResult = videoApi.findByVidList(vidList, page, pagesize);

        return pageResult;
    }

    /**
     * 视频上传
     */
    @CacheEvict(value = "videoList", allEntries = true)
    public ResponseEntity<Object> uploadVideo(MultipartFile videoThumbnail, MultipartFile videoFile) throws Exception {
        // 1.创建video对象
        Video video = new Video();
        video.setUserId(UserHolder.getUserId());
        video.setText("左手右手一个慢动作~");
        video.setCreated(System.currentTimeMillis());

        // 2.上传封面文件到阿里云oss
        if (videoThumbnail != null) {
            String picUrl = ossTemplate.upload(videoThumbnail.getOriginalFilename(), videoThumbnail.getInputStream());
            video.setPicUrl(picUrl);
        }

        // 3.上传小视频文件到FastDFS
        if (videoFile != null) {
            // 例如：123.mp4
            String fileName = videoFile.getOriginalFilename();
            String extName = fileName.substring(fileName.lastIndexOf(".") + 1);
            StorePath storePath = fastFileStorageClient.uploadFile(videoFile.getInputStream(),
                    videoFile.getSize(), extName, null);
            // 获取小视频存储的完整url
            String videoUrl = fdfsWebServer.getWebServerUrl() + storePath.getFullPath();
            video.setVideoUrl(videoUrl);
        }

        // 4.调用服务提供者api保存小视频数据
        video.setId(ObjectId.get()); // 手动设置id
        videoApi.save(video);

        // 5.发送评分数据消息到RocketMQ
        videoMQService.sendMsg(video.getId().toString(), 1);

        return ResponseEntity.ok(null);
    }

    /**
     * 视频用户关注
     */
    public ResponseEntity<Object> followUser(Long uid) {
        // 1.保存数据到用户关注表
        FollowUser followUser = new FollowUser();
        followUser.setCreated(System.currentTimeMillis());
        followUser.setUserId(UserHolder.getUserId());
        followUser.setFollowUserId(uid);

        videoApi.followUser(followUser);

        // 2.存储关注的标记到redis，key必须唯一：userId + followUserId
        String key = "followUser_" + UserHolder.getUserId() + "_" + uid;
        redisTemplate.opsForValue().set(key, "xxx");



        return ResponseEntity.ok(null);
    }

    /**
     * 视频用户关注 - 取消
     */
    public ResponseEntity<Object> unfollowUser(Long uid) {
        // 1.删除用户关注表的数据
        videoApi.unfollowUser(UserHolder.getUserId(), uid);

        // 2.删除关注的标记
        String key = "followUser_" + UserHolder.getUserId() + "_" + uid;
        redisTemplate.delete(key);

        return ResponseEntity.ok(null);

    }


    /**
     * 接口名称：视频点赞
     */
    public ResponseEntity<Object> likeVideo(String id) {
        // 1.创建评论对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(id)); // 动态id
        comment.setCommentType(1);  // 评论类型：1-点赞，2-评论，3-喜欢
        comment.setPubType(2); // 评论内容类型：1-对动态操作 2-对视频操作 3-对评论操作
        comment.setUserId(UserHolder.getUserId());
        comment.setCreated(System.currentTimeMillis());

        // 2.调用服务提供者保存评论数据、修改动态表点赞数量、返回点赞数量
        long count =commentApi.save(comment);

        // 3.往redis存入一个点赞标记，key必须唯一：userId + publishId
        String key = "public_like_video_" + UserHolder.getUserId() + "_" + id;
        redisTemplate.opsForValue().set(key, "点赞");

        return ResponseEntity.ok(count);


    }

    /**
     * 接口名称：视频点赞 - 取消
     */
    public ResponseEntity<Object> dislikeVideo(String id) {
        // 1.创建评论对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(id)); // 动态id
        comment.setCommentType(1);  // 评论类型：1-点赞，2-评论，3-喜欢
        comment.setPubType(2); // 评论内容类型：1-对动态操作 2-对视频操作 3-对评论操作
        comment.setUserId(UserHolder.getUserId());

        // 2.调用服务提供者删除评论数据、修改动态表点赞数量、返回点赞数量
        long count = commentApi.delete(comment);

        // 3.删除redis点赞标记，key必须唯一：userId + publishId
        String key = "public_like_video_" + UserHolder.getUserId() + "_" + id;
        redisTemplate.delete(key);

        return ResponseEntity.ok(count);
    }

}
